import glob
import os
import pandas as pd
import numpy as np
import seaborn as sns
%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm, Normalize
from matplotlib_venn import venn2
from datetime import datetime
from ast import literal_eval
# Attributes to split monsters query
attributes = ['DIVINE', 'LIGHT', 'DARK', 'WATER', 'EARTH', 'FIRE', 'WIND']
# API variables
api_url = 'https://yugipedia.com/api.php'
# Styling dictionaries
arrows_dict = {'Middle-Left': '\u2190', 'Middle-Right': '\u2192', 'Top-Left': '\u2196', 'Top-Center': '\u2191', 'Top-Right': '\u2197', 'Bottom-Left': '\u2199', 'Bottom-Center': '\u2193', 'Bottom-Right': '\u2198'}
card_colors = {'Effect Monster': '#FF8B53', 'Normal Monster': '#FDE68A', 'Ritual Monster': '#9DB5CC', 'Fusion Monster': '#A086B7', 'Synchro Monster': '#CCCCCC', 'Xyz Monster': '#000000', 'Link Monster': '#00008B', 'Pendulum Monster': 'r', 'Monster Card': '#FF8B53', 'Spell Card': '#1D9E74', 'Trap Card': '#BC5A84', 'Monster Token': '#C0C0C0', 'FIRE': '#fd1b1b', 'WATER': '#03a9e6', 'EARTH': '#060d0a', 'WIND': '#77bb58', 'DARK': '#745ea5', 'LIGHT': '#9d8047', 'DIVINE': '#7e6537', 'Level': '#f1a41f'}
def extract_results(df):
df = pd.DataFrame(df['query']['results']).transpose()
df = pd.DataFrame(df['printouts'].values.tolist())
return df
def extract_artwork(row):
result = tuple()
if 'Category:OCG/TCG cards with alternate artworks' in row:
result += ('Alternate',)
if 'Category:OCG/TCG cards with edited artworks' in row:
result += ('Edited',)
if result == tuple():
return np.nan
else:
return result
def concat_errata(row):
result = tuple()
if row['Name errata']:
result += ('Name',)
if row['Type errata']:
result += ('Type',)
if result == tuple():
return np.nan
else:
return result
def format_df(input_df, input_errata_df):
df = pd.DataFrame()
if 'Name' in input_df.columns:
df['Name'] = input_df['Name'].dropna().apply(lambda x: x[0])
if 'Password' in input_df.columns:
df['Password'] = input_df['Password'].dropna().apply(lambda x: x[0] if len(x)>0 else np.nan)
if 'Card type' in input_df.columns:
df['Card type'] = input_df['Card type'].dropna().apply(lambda x: x[0]['fulltext'] if len(x)>0 else np.nan)
if 'Property' in input_df.columns:
df['Property'] = input_df['Property'].dropna().apply(lambda x: x[0] if len(x)>0 else np.nan)
if 'Primary type' in input_df.columns:
df['Primary type'] = input_df['Primary type'].dropna().apply(lambda x: [i['fulltext'] for i in x] if len(x)>0 else []).apply(lambda y: list(filter(lambda z: z != 'Pendulum Monster', y)) if len(y)>0 else []).apply(lambda y: list(filter(lambda z: z != 'Effect Monster', y))[0] if len(y)>1 else (y[0] if len(y)>0 else np.nan))
if 'Secondary type' in input_df.columns:
df['Secondary type'] = input_df['Secondary type'].dropna().apply(lambda x: x[0]['fulltext'] if len(x)>0 else np.nan)
if 'Attribute' in input_df.columns:
df['Attribute'] = input_df['Attribute'].dropna().apply(lambda x: x[0]['fulltext'] if len(x)>0 else np.nan)
if 'Monster type' in input_df.columns:
df['Monster type'] = input_df['Monster type'].dropna().apply(lambda x: x[0]['fulltext'] if len(x)>0 else np.nan)
if 'Level/Rank' in input_df.columns:
df['Level/Rank'] = input_df['Level/Rank'].dropna().apply(lambda x: x[0] if len(x)>0 else np.nan)
if 'ATK' in input_df.columns:
df['ATK'] = input_df['ATK'].dropna().apply(lambda x: x[0] if len(x)>0 else np.nan)
if 'DEF' in input_df.columns:
df['DEF'] = input_df['DEF'].dropna().apply(lambda x: x[0] if len(x)>0 else np.nan)
if 'Pendulum Scale' in input_df.columns:
df['Pendulum Scale'] = input_df['Pendulum Scale'].dropna().apply(lambda x: str(x[0]) if len(x)>0 else np.nan)
if 'Link' in input_df.columns:
df['Link'] = input_df['Link'].dropna().apply(lambda x: str(x[0]) if len(x)>0 else np.nan)
if 'Link Arrows' in input_df.columns:
df['Link Arrows'] = input_df['Link Arrows'].dropna().apply(lambda x: tuple([arrows_dict[i] for i in sorted(x)]) if len(x)>0 else np.nan)
if 'Effect type' in input_df.columns:
df['Effect type'] = input_df['Effect type'].dropna().apply(lambda x: tuple(sorted([i['fulltext'] for i in x])) if len(x)>0 else np.nan)
if 'Archseries' in input_df.columns:
df['Archseries'] = input_df['Archseries'].dropna().apply(lambda x: tuple(sorted(x)) if len(x)>0 else np.nan)
if 'Category' in input_df.columns:
df['Artwork'] = input_df['Category'].dropna().apply(lambda x: [i['fulltext'] for i in x] if len(x)>0 else np.nan).apply(extract_artwork)
# Erratas column
if input_errata_df is not None and 'Page name' in input_df.columns:
df['Errata'] = errata_df.merge(input_df['Page name'].dropna().apply(lambda x: x[0]).rename('Name'), right_on = 'Name', left_index = True).apply(concat_errata,axis = 1)
#################
if 'TCG status' in input_df.columns:
df['TCG status'] = input_df['TCG status'].dropna().apply(lambda x: x[0]['fulltext'] if len(x)>0 else np.nan)
if 'OCG status' in input_df.columns:
df['OCG status'] = input_df['OCG status'].dropna().apply(lambda x: x[0]['fulltext'] if len(x)>0 else np.nan)
if 'Modification date' in input_df.columns:
df['Modification date'] = input_df['Modification date'].dropna().apply(lambda x: pd.Timestamp(int(x[0]['timestamp']), unit='s').ctime() if len(x)>0 else np.nan)
return df
def card_query(_password = True, _card_type = True, _property = True, _primary = True, _secondary = True, _attribute = True, _monster_type = True, _stars = True, _atk = True, _def = True, _scale = True, _link = True, _arrows = True, _effect_type = True, _archseries = True, _category = True, _tcg = True, _ocg = True, _date = True, _page_name = True):
search_string = f'|?English%20name=Name'
if _password:
search_string += '|?Password'
if _card_type:
search_string += '|?Card%20type'
if _property:
search_string += '|?Property'
if _primary:
search_string += '|?Primary%20type'
if _secondary:
search_string += '|?Secondary%20type'
if _attribute:
search_string += '|?Attribute'
if _monster_type:
search_string += '|?Type=Monster%20type'
if _stars:
search_string += '|?Stars%20string=Level%2FRank%20'
if _atk:
search_string += '|?ATK%20string=ATK'
if _def:
search_string += '|?DEF%20string=DEF'
if _scale:
search_string += '|?Pendulum%20Scale'
if _link:
search_string += '|?Link%20Rating=Link'
if _arrows:
search_string += '|?Link%20Arrows'
if _effect_type:
search_string += '|?Effect%20type'
if _archseries:
search_string += '|?Archseries'
if _category:
search_string += '|?category'
if _tcg:
search_string += '|?TCG%20status'
if _ocg:
search_string += '|?OCG%20status'
if _date:
search_string += '|?Modification%20date'
if _page_name:
search_string += '|?Page%20name'
return search_string
def fetch_spell(spell_query, step = 5000, limit = 5000):
print('Downloading Spells')
spell_df = pd.DataFrame()
for i in range(int(limit/step)):
df = pd.read_json(f'{api_url}?action=ask&query=[[Concept:CG%20Spell%20Cards]]{spell_query}|limit%3D{step}|offset={i*step}|order%3Dasc&format=json')
df = extract_results(df)
print(f'Iteration {i+1}: {len(df.index)} results')
spell_df = pd.concat([spell_df, df], ignore_index=True, axis=0)
if len(df.index)<step:
break
print(f'- Total\n{len(spell_df.index)} results\n')
return spell_df
def fetch_trap(trap_query, step = 5000, limit = 5000):
print('Downloading Traps')
trap_df = pd.DataFrame()
for i in range(int(limit/step)):
df = pd.read_json(f'{api_url}?action=ask&query=[[Concept:CG%20Trap%20Cards]]{trap_query}|limit%3D{step}|offset={i*step}|order%3Dasc&format=json')
df = extract_results(df)
print(f'Iteration {i+1}: {len(df.index)} results')
trap_df = pd.concat([trap_df, df], ignore_index=True, axis=0)
if len(df.index)<step:
break
print(f'- Total\n{len(trap_df.index)} results\n')
return trap_df
def fetch_monster(monster_query, step = 5000, limit = 5000):
print('Downloading Monsters')
monster_df = pd.DataFrame()
for att in attributes:
print(f"- {att}")
for i in range(int(limit/step)):
df = pd.read_json(f'{api_url}?action=ask&query=[[Concept:CG%20monsters]][[Attribute::{att}]]{monster_query}|limit%3D{step}|offset={i*step}|order%3Dasc&format=json')
df = extract_results(df)
print(f'Iteration {i+1}: {len(df.index)} results')
monster_df = pd.concat([monster_df, df], ignore_index=True, axis=0)
if len(df.index)<step:
break
print(f'- Total\n{len(monster_df.index)} results')
return monster_df
def fetch_name_errata(limit = 1000):
name_query_df = pd.read_json(f'{api_url}?action=ask&query=[[Category:Cards%20with%20name%20errata]]|limit={limit}|order%3Dasc&format=json')
name_keys = list(name_query_df['query']['results'].keys())
return pd.DataFrame(True, index = [i.split(':')[1].strip() for i in name_keys if 'Card Errata:' in i], columns = ['Name errata'])
def fetch_type_errata(limit = 1000):
type_query_df = pd.read_json(f'{api_url}?action=ask&query=[[Category:Cards%20with%20card%20type%20errata]]|limit={limit}|order%3Dasc&format=json')
type_keys = list(type_query_df['query']['results'].keys())
return pd.DataFrame(True, index = [i.split(':')[1].strip() for i in type_keys if 'Card Errata:' in i], columns = ['Type errata'])
monster_query = card_query(_property = False)
st_query = card_query(_primary = False, _secondary = False, _attribute = False, _monster_type = False, _stars = False, _atk = False, _def = False, _scale = False, _link = False, _arrows = False)
# Timestamp
timestamp = pd.Timestamp.now().timestamp()
full_df = pd.DataFrame()
# Fetch Spell
spell_df = fetch_spell(st_query, step = 1000, limit = 3000)
full_df = pd.concat([full_df, spell_df], ignore_index=True, axis=0)
# Fetch Trap
trap_df = fetch_trap(st_query, step = 1000, limit = 3000)
full_df = pd.concat([full_df, trap_df], ignore_index=True, axis=0)
st_df = pd.concat([spell_df, trap_df], ignore_index=True, axis=0)
# Fetch Monster
monster_df = fetch_monster(monster_query, step = 1000, limit = 5000)
full_df = pd.concat([full_df, monster_df], ignore_index=True, axis=0)
# Fetch errata
errata_df = pd.concat([fetch_name_errata(), fetch_type_errata()], axis=1).fillna(False)
Downloading Spells Iteration 1: 1000 results Iteration 2: 1000 results Iteration 3: 362 results - Total 2362 results Downloading Traps Iteration 1: 1000 results Iteration 2: 800 results - Total 1800 results Downloading Monsters - DIVINE Iteration 1: 9 results - LIGHT Iteration 1: 1000 results Iteration 2: 614 results - DARK Iteration 1: 1000 results Iteration 2: 1000 results Iteration 3: 210 results - WATER Iteration 1: 833 results - EARTH Iteration 1: 1000 results Iteration 2: 867 results - FIRE Iteration 1: 665 results - WIND Iteration 1: 760 results - Total 7958 results
formatted_spell_df = format_df(spell_df, errata_df)
formatted_trap_df = format_df(trap_df, errata_df)
formatted_st_df = format_df(st_df, errata_df)
formatted_monster_df = format_df(monster_df, errata_df)
formatted_full_df = format_df(full_df, errata_df)
print('Data formated')
Data formated
formatted_full_df.to_csv(f'Data/All_cards_{int(timestamp)}.csv', index = False)
print('Data saved')
Data saved
# Get list of files
list_of_files = sorted(glob.glob('Data/All_cards_*.csv'), key=os.path.getctime, reverse=True)
# Get second newest file if exist
if len(list_of_files)>1:
latest_file = list_of_files[1]
previous_df = pd.read_csv(latest_file, dtype=object)
# Correct tuples
previous_df['Effect type'] = previous_df['Effect type'].dropna().apply(literal_eval)
previous_df['Link Arrows'] = previous_df['Link Arrows'].dropna().apply(literal_eval)
previous_df['Archseries'] = previous_df['Archseries'].dropna().apply(literal_eval)
previous_df['Artwork'] = previous_df['Artwork'].dropna().apply(literal_eval)
previous_df['Errata'] = previous_df['Errata'].dropna().apply(literal_eval)
print('File loaded')
else:
print('No older files')
File loaded
if previous_df is not None:
changelog = previous_df.merge(formatted_full_df,indicator = True, how='outer').loc[lambda x : x['_merge']!='both'].sort_values('Name', ignore_index=True)
changelog['_merge'].replace(['left_only','right_only'],['Old', 'New'], inplace = True)
changelog.rename(columns={"_merge": "Version"}, inplace = True)
nunique = changelog.groupby('Name').nunique()
cols_to_drop = nunique[nunique < 2].dropna(axis=1).columns
changelog = changelog.set_index('Name')[nunique > 1]
changelog.drop(cols_to_drop, axis=1, inplace = True)
changelog
else:
print('No changes')
formatted_full_df
| Name | Password | Card type | Property | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | ... | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | "A" Cell Breeding Device | 34541863 | Spell Card | Continuous Spell Card | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | (Trigger Effect,) | NaN | NaN | (Name,) | Unlimited | Unlimited | Sat Nov 6 13:57:15 2021 |
| 1 | "A" Cell Incubator | 64163367 | Spell Card | Continuous Spell Card | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | (Continuous-like Effect, Trigger Effect) | NaN | NaN | NaN | Unlimited | Unlimited | Mon Jun 13 04:27:51 2022 |
| 2 | "A" Cell Recombination Device | 91231901 | Spell Card | Quick-Play Spell Card | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | (Effect, Ignition-like Effect) | NaN | NaN | NaN | Unlimited | Unlimited | Thu Mar 12 22:40:14 2020 |
| 3 | "A" Cell Scatter Burst | 73262676 | Spell Card | Quick-Play Spell Card | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | (Effect,) | NaN | NaN | NaN | Unlimited | Unlimited | Sat Nov 6 13:58:32 2021 |
| 4 | "Infernoble Arms - Durendal" | 37478723 | Spell Card | Equip Spell Card | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | (Condition, Ignition-like Effect, Trigger Effect) | (Noble Arms,) | NaN | NaN | Unlimited | Unlimited | Sat Aug 20 13:52:48 2022 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 12115 | Yosenju Shinchu L | 65025250 | Monster Card | NaN | Effect Monster | NaN | WIND | Rock | 4 | 0 | ... | 3 | NaN | NaN | (Continuous Effect, Continuous-like Effect, Tr... | (Yosenju,) | NaN | NaN | Unlimited | Unlimited | Sun Aug 14 11:04:00 2022 |
| 12116 | Yosenju Shinchu R | 91420254 | Monster Card | NaN | Effect Monster | NaN | WIND | Rock | 4 | 0 | ... | 5 | NaN | NaN | (Continuous Effect, Ignition-like Effect, Trig... | (Yosenju,) | NaN | NaN | Unlimited | Unlimited | Sat Aug 13 12:21:48 2022 |
| 12117 | Yosenju Tsujik | 25244515 | Monster Card | NaN | Effect Monster | NaN | WIND | Beast-Warrior | 4 | 1000 | ... | NaN | NaN | NaN | (Condition, Ignition Effect, Quick Effect, Tri... | (Yosenju,) | NaN | NaN | Unlimited | Unlimited | Sun Dec 20 18:15:02 2020 |
| 12118 | ZW - Eagle Claw | 29353756 | Monster Card | NaN | Effect Monster | NaN | WIND | Winged Beast | 5 | 2000 | ... | NaN | NaN | NaN | (Continuous-like Effect, Ignition Effect, Uncl... | (ZW -, Zexal) | NaN | NaN | Unlimited | Unlimited | Thu Jul 8 13:48:07 2021 |
| 12119 | ZW - Tornado Bringer | 81471108 | Monster Card | NaN | Effect Monster | NaN | WIND | Dragon | 5 | 1300 | ... | NaN | NaN | NaN | (Continuous-like Effect, Ignition Effect, Uncl... | (ZW -, Zexal) | NaN | NaN | Unlimited | Unlimited | Sun Aug 14 11:04:24 2022 |
12120 rows × 21 columns
formatted_full_df.groupby('Card type').nunique()
| Name | Password | Property | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Card type | ||||||||||||||||||||
| Monster Card | 7950 | 7817 | 0 | 8 | 6 | 7 | 25 | 15 | 82 | 77 | 13 | 6 | 61 | 223 | 984 | 3 | 3 | 7 | 7 | 7912 |
| Spell Card | 2360 | 2331 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 114 | 394 | 3 | 3 | 6 | 6 | 2350 |
| Trap Card | 1800 | 1779 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 95 | 323 | 3 | 3 | 5 | 6 | 1794 |
card_type_colors = [card_colors[i] for i in formatted_full_df['Card type'].value_counts().index]
formatted_full_df['Card type'].value_counts().plot.bar(figsize = (18,6), grid = True, rot=0, color = card_type_colors)
plt.show()
print('Total number of attributes:', formatted_monster_df['Attribute'].nunique())
Total number of attributes: 7
formatted_monster_df.drop(columns=['Card type']).groupby('Attribute').nunique()
| Name | Password | Primary type | Secondary type | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Attribute | ||||||||||||||||||
| DARK | 2207 | 2173 | 7 | 6 | 23 | 14 | 70 | 63 | 12 | 6 | 39 | 153 | 447 | 3 | 3 | 7 | 7 | 2204 |
| DIVINE | 6 | 0 | 1 | 0 | 2 | 2 | 3 | 3 | 0 | 0 | 0 | 6 | 3 | 1 | 3 | 2 | 2 | 9 |
| EARTH | 1865 | 1840 | 7 | 6 | 23 | 12 | 71 | 60 | 12 | 4 | 29 | 127 | 327 | 3 | 3 | 6 | 6 | 1861 |
| FIRE | 665 | 657 | 8 | 6 | 22 | 12 | 43 | 40 | 8 | 4 | 22 | 85 | 184 | 3 | 3 | 4 | 6 | 663 |
| LIGHT | 1614 | 1575 | 7 | 6 | 23 | 14 | 58 | 50 | 10 | 5 | 30 | 131 | 381 | 3 | 3 | 6 | 7 | 1607 |
| WATER | 833 | 820 | 7 | 6 | 22 | 11 | 56 | 41 | 9 | 4 | 16 | 92 | 203 | 3 | 3 | 6 | 7 | 833 |
| WIND | 760 | 752 | 7 | 6 | 23 | 12 | 46 | 38 | 11 | 4 | 14 | 104 | 211 | 3 | 3 | 6 | 6 | 756 |
attribute_colors = [card_colors[i] for i in formatted_full_df['Attribute'].value_counts().index]
formatted_monster_df['Attribute'].value_counts().plot.bar(figsize = (18,6), grid = True, rot=0, color = attribute_colors)
plt.show()
print('Total number of primary types:', formatted_monster_df['Primary type'].nunique())
Total number of primary types: 8
formatted_monster_df.drop(columns=['Card type']).groupby('Primary type').nunique()
| Name | Password | Secondary type | Attribute | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Primary type | ||||||||||||||||||
| Effect Monster | 5400 | 5345 | 6 | 7 | 25 | 12 | 73 | 66 | 13 | 0 | 0 | 203 | 769 | 3 | 3 | 6 | 6 | 5374 |
| Fusion Monster | 424 | 419 | 1 | 6 | 23 | 12 | 48 | 46 | 4 | 0 | 0 | 67 | 140 | 3 | 3 | 4 | 6 | 423 |
| Link Monster | 366 | 358 | 0 | 6 | 23 | 0 | 38 | 0 | 0 | 6 | 61 | 51 | 138 | 3 | 2 | 5 | 5 | 366 |
| Monster Token | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
| Normal Monster | 745 | 701 | 1 | 6 | 23 | 10 | 59 | 49 | 10 | 0 | 0 | 6 | 129 | 3 | 3 | 4 | 4 | 746 |
| Ritual Monster | 119 | 117 | 3 | 6 | 15 | 12 | 33 | 26 | 1 | 0 | 0 | 33 | 37 | 2 | 3 | 2 | 2 | 119 |
| Synchro Monster | 410 | 400 | 1 | 6 | 23 | 13 | 40 | 38 | 4 | 0 | 0 | 56 | 155 | 2 | 3 | 5 | 5 | 410 |
| Xyz Monster | 489 | 477 | 0 | 6 | 23 | 14 | 51 | 42 | 4 | 0 | 0 | 68 | 190 | 3 | 2 | 5 | 5 | 487 |
has_effect = formatted_monster_df['Primary type'].where(formatted_monster_df['Effect type'].notna()).value_counts().rename('Effect')
no_effect = formatted_monster_df['Primary type'].where(formatted_monster_df['Effect type'].isna()).value_counts().rename('No Effect')
effect = pd.concat([has_effect,no_effect], axis=1)
effect
| Effect | No Effect | |
|---|---|---|
| Effect Monster | 5399.0 | 1 |
| Xyz Monster | 487.0 | 2 |
| Synchro Monster | 407.0 | 3 |
| Fusion Monster | 362.0 | 62 |
| Link Monster | 360.0 | 6 |
| Ritual Monster | 103.0 | 16 |
| Normal Monster | 34.0 | 712 |
| Monster Token | NaN | 1 |
monster_type_colors = {'No Effect': card_colors['Normal Monster'], 'Effect': [card_colors[i] for i in effect.index]}
effect.plot.bar(figsize = (18,6), stacked = True, grid = True, rot=0, legend=True, color = monster_type_colors)
plt.show()
Normal monster can have effect if it is pendulum
not_pendulum = formatted_monster_df['Primary type'].where(formatted_monster_df['Pendulum Scale'].isna()).value_counts().rename('Not Pendulum')
is_pendulum = formatted_monster_df['Primary type'].where(formatted_monster_df['Pendulum Scale'].notna()).value_counts().rename('Pendulum')
pendulum = pd.concat([not_pendulum,is_pendulum], axis=1)
pendulum
| Not Pendulum | Pendulum | |
|---|---|---|
| Effect Monster | 5138 | 262.0 |
| Normal Monster | 708 | 38.0 |
| Xyz Monster | 482 | 7.0 |
| Fusion Monster | 414 | 10.0 |
| Synchro Monster | 404 | 6.0 |
| Link Monster | 366 | NaN |
| Ritual Monster | 118 | 1.0 |
| Monster Token | 1 | NaN |
monster_type_colors_b = {'Pendulum': card_colors['Pendulum Monster'], 'Not Pendulum': [card_colors[i] for i in pendulum.index]}
pendulum.plot.bar(figsize = (18,6), stacked = True, grid = True, rot=0, color = monster_type_colors_b, legend=True)
plt.show()
primmary_crosstab = pd.crosstab(formatted_full_df['Primary type'],formatted_full_df['Attribute'])
primmary_crosstab
| Attribute | DARK | DIVINE | EARTH | FIRE | LIGHT | WATER | WIND |
|---|---|---|---|---|---|---|---|
| Primary type | |||||||
| Effect Monster | 1483 | 6 | 1296 | 450 | 1089 | 550 | 526 |
| Fusion Monster | 146 | 0 | 81 | 34 | 96 | 34 | 33 |
| Link Monster | 119 | 0 | 74 | 33 | 86 | 29 | 25 |
| Monster Token | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
| Normal Monster | 186 | 0 | 250 | 52 | 82 | 109 | 67 |
| Ritual Monster | 35 | 0 | 17 | 7 | 34 | 20 | 6 |
| Synchro Monster | 107 | 0 | 69 | 50 | 74 | 36 | 74 |
| Xyz Monster | 134 | 0 | 80 | 38 | 153 | 55 | 29 |
plt.figure(figsize = (16,10))
sns.heatmap(primmary_crosstab.T, annot=True, fmt="g", cmap='viridis', square=True, norm=LogNorm())
plt.show()
print('Total number of secondary types:', formatted_monster_df['Secondary type'].nunique())
Total number of secondary types: 6
formatted_monster_df.drop(columns=['Card type', 'Link', 'Link Arrows']).groupby('Secondary type').nunique()
| Name | Password | Primary type | Attribute | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Secondary type | ||||||||||||||||
| Flip monster | 183 | 182 | 2 | 6 | 19 | 12 | 38 | 33 | 1 | 20 | 45 | 2 | 3 | 4 | 4 | 183 |
| Gemini monster | 45 | 45 | 1 | 6 | 18 | 8 | 17 | 19 | 0 | 6 | 13 | 0 | 3 | 1 | 1 | 45 |
| Spirit monster | 37 | 37 | 2 | 6 | 13 | 9 | 22 | 20 | 2 | 7 | 4 | 1 | 1 | 3 | 2 | 37 |
| Toon monster | 17 | 17 | 1 | 6 | 7 | 5 | 12 | 15 | 0 | 8 | 13 | 1 | 2 | 1 | 2 | 17 |
| Tuner monster | 466 | 461 | 5 | 6 | 23 | 9 | 32 | 32 | 7 | 57 | 131 | 3 | 3 | 4 | 4 | 465 |
| Union monster | 37 | 37 | 1 | 6 | 9 | 8 | 17 | 14 | 0 | 6 | 9 | 1 | 2 | 1 | 1 | 37 |
secondary_type_colors = card_colors['Effect Monster']
formatted_monster_df['Secondary type'].value_counts().plot.bar(figsize = (18,6), stacked = True, grid = True, rot=0, color = secondary_type_colors, legend=True)
plt.show()
secondary_crosstab = pd.crosstab(formatted_full_df['Secondary type'],formatted_full_df['Attribute'])
secondary_crosstab
| Attribute | DARK | EARTH | FIRE | LIGHT | WATER | WIND |
|---|---|---|---|---|---|---|
| Secondary type | ||||||
| Flip monster | 51 | 61 | 10 | 31 | 13 | 17 |
| Gemini monster | 11 | 8 | 8 | 6 | 8 | 4 |
| Spirit monster | 5 | 6 | 6 | 4 | 6 | 10 |
| Toon monster | 7 | 5 | 1 | 2 | 1 | 1 |
| Tuner monster | 119 | 91 | 42 | 94 | 51 | 69 |
| Union monster | 6 | 9 | 3 | 12 | 4 | 3 |
plt.figure(figsize = (8,6))
sns.heatmap(secondary_crosstab, annot=True, fmt="g", cmap='viridis', square=True)
plt.show()
secondary_crosstab_b = pd.crosstab(formatted_full_df['Primary type'],formatted_full_df['Secondary type'], margins = True)
secondary_crosstab_b
| Secondary type | Flip monster | Gemini monster | Spirit monster | Toon monster | Tuner monster | Union monster | All |
|---|---|---|---|---|---|---|---|
| Primary type | |||||||
| Effect Monster | 182 | 45 | 35 | 17 | 420 | 37 | 736 |
| Fusion Monster | 0 | 0 | 0 | 0 | 3 | 0 | 3 |
| Normal Monster | 0 | 0 | 0 | 0 | 12 | 0 | 12 |
| Ritual Monster | 1 | 0 | 2 | 0 | 1 | 0 | 4 |
| Synchro Monster | 0 | 0 | 0 | 0 | 30 | 0 | 30 |
| All | 183 | 45 | 37 | 17 | 466 | 37 | 785 |
plt.figure(figsize = (10,7))
sns.heatmap(secondary_crosstab_b, annot=True, fmt="g", cmap='viridis', square=True, norm=LogNorm())
plt.show()
print('Total number of monster types:', formatted_monster_df['Monster type'].nunique())
Total number of monster types: 25
formatted_monster_df.drop(columns=['Card type']).groupby('Monster type').nunique()
| Name | Password | Primary type | Secondary type | Attribute | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Monster type | ||||||||||||||||||
| Aqua | 255 | 252 | 7 | 6 | 6 | 10 | 50 | 33 | 3 | 2 | 3 | 50 | 64 | 2 | 3 | 5 | 6 | 255 |
| Beast | 376 | 368 | 7 | 4 | 6 | 10 | 48 | 38 | 7 | 2 | 7 | 59 | 84 | 3 | 3 | 5 | 5 | 377 |
| Beast-Warrior | 236 | 232 | 7 | 3 | 6 | 10 | 36 | 29 | 6 | 3 | 7 | 57 | 47 | 3 | 3 | 5 | 5 | 235 |
| Creator God | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
| Cyberse | 246 | 244 | 7 | 1 | 6 | 11 | 30 | 29 | 1 | 6 | 38 | 45 | 34 | 2 | 2 | 4 | 4 | 246 |
| Dinosaur | 122 | 120 | 6 | 1 | 6 | 10 | 35 | 30 | 4 | 2 | 3 | 35 | 24 | 1 | 2 | 4 | 3 | 122 |
| Divine-Beast | 5 | 0 | 1 | 0 | 1 | 1 | 3 | 3 | 0 | 0 | 0 | 5 | 2 | 1 | 3 | 2 | 2 | 8 |
| Dragon | 655 | 648 | 7 | 6 | 6 | 13 | 52 | 48 | 9 | 5 | 19 | 109 | 184 | 2 | 3 | 6 | 6 | 652 |
| Fairy | 509 | 497 | 7 | 5 | 6 | 12 | 43 | 38 | 9 | 4 | 12 | 80 | 110 | 3 | 3 | 6 | 6 | 506 |
| Fiend | 763 | 746 | 7 | 6 | 6 | 13 | 60 | 45 | 12 | 5 | 14 | 106 | 147 | 3 | 3 | 6 | 6 | 763 |
| Fish | 127 | 121 | 7 | 2 | 5 | 10 | 34 | 28 | 1 | 1 | 1 | 30 | 21 | 2 | 2 | 3 | 3 | 127 |
| Insect | 243 | 236 | 7 | 3 | 6 | 12 | 45 | 34 | 2 | 3 | 6 | 58 | 39 | 2 | 2 | 3 | 3 | 243 |
| Machine | 915 | 900 | 7 | 5 | 6 | 12 | 62 | 55 | 9 | 4 | 22 | 111 | 167 | 3 | 3 | 6 | 7 | 910 |
| Plant | 231 | 228 | 6 | 4 | 6 | 9 | 37 | 30 | 5 | 4 | 9 | 38 | 38 | 2 | 2 | 4 | 5 | 231 |
| Psychic | 177 | 173 | 6 | 2 | 6 | 11 | 35 | 31 | 5 | 2 | 3 | 42 | 42 | 1 | 2 | 5 | 5 | 177 |
| Pyro | 121 | 120 | 7 | 5 | 5 | 11 | 34 | 29 | 0 | 1 | 1 | 36 | 33 | 1 | 3 | 1 | 3 | 121 |
| Reptile | 171 | 170 | 6 | 3 | 6 | 11 | 37 | 30 | 3 | 2 | 3 | 46 | 35 | 0 | 2 | 4 | 3 | 171 |
| Rock | 247 | 244 | 7 | 4 | 6 | 11 | 43 | 40 | 4 | 3 | 4 | 60 | 73 | 1 | 3 | 5 | 6 | 246 |
| Sea Serpent | 82 | 82 | 6 | 3 | 6 | 10 | 28 | 26 | 1 | 2 | 2 | 32 | 28 | 2 | 3 | 3 | 2 | 82 |
| Spellcaster | 674 | 662 | 7 | 5 | 6 | 12 | 50 | 41 | 10 | 5 | 12 | 100 | 146 | 3 | 3 | 6 | 7 | 672 |
| Thunder | 128 | 125 | 6 | 4 | 6 | 10 | 35 | 29 | 1 | 2 | 4 | 37 | 33 | 1 | 2 | 4 | 4 | 128 |
| Warrior | 1024 | 1015 | 7 | 6 | 6 | 13 | 60 | 41 | 6 | 3 | 15 | 92 | 215 | 3 | 3 | 7 | 7 | 1022 |
| Winged Beast | 313 | 309 | 7 | 5 | 6 | 10 | 39 | 29 | 4 | 4 | 6 | 61 | 65 | 2 | 3 | 5 | 5 | 313 |
| Wyrm | 87 | 85 | 6 | 1 | 6 | 11 | 26 | 24 | 3 | 4 | 6 | 33 | 20 | 1 | 1 | 3 | 3 | 87 |
| Zombie | 242 | 240 | 7 | 5 | 6 | 12 | 38 | 37 | 1 | 3 | 5 | 51 | 35 | 2 | 3 | 2 | 2 | 241 |
monster_type_colors = card_colors['Monster Card']
formatted_monster_df['Monster type'].value_counts().plot.bar(figsize = (18,6), grid = True, rot=45, color = monster_type_colors)
plt.show()
monster_crosstab = pd.crosstab(formatted_full_df['Monster type'],formatted_full_df['Attribute'], dropna=False)
monster_crosstab
| Attribute | DARK | DIVINE | EARTH | FIRE | LIGHT | WATER | WIND |
|---|---|---|---|---|---|---|---|
| Monster type | |||||||
| Aqua | 9 | 0 | 6 | 10 | 4 | 220 | 6 |
| Beast | 37 | 0 | 213 | 16 | 72 | 14 | 25 |
| Beast-Warrior | 37 | 0 | 82 | 53 | 33 | 16 | 15 |
| Creator God | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| Cyberse | 63 | 0 | 36 | 44 | 63 | 28 | 12 |
| Dinosaur | 11 | 0 | 60 | 32 | 5 | 8 | 6 |
| Divine-Beast | 0 | 8 | 0 | 0 | 0 | 0 | 0 |
| Dragon | 252 | 0 | 47 | 48 | 167 | 28 | 113 |
| Fairy | 55 | 0 | 62 | 17 | 324 | 26 | 25 |
| Fiend | 575 | 0 | 34 | 47 | 70 | 23 | 16 |
| Fish | 2 | 0 | 2 | 0 | 1 | 120 | 2 |
| Insect | 37 | 0 | 132 | 6 | 20 | 4 | 44 |
| Machine | 224 | 0 | 309 | 51 | 167 | 48 | 116 |
| Plant | 42 | 0 | 118 | 11 | 22 | 24 | 14 |
| Psychic | 23 | 0 | 37 | 17 | 45 | 13 | 42 |
| Pyro | 2 | 0 | 6 | 106 | 4 | 0 | 3 |
| Reptile | 39 | 0 | 34 | 15 | 45 | 34 | 4 |
| Rock | 16 | 0 | 199 | 5 | 15 | 5 | 7 |
| Sea Serpent | 3 | 0 | 1 | 1 | 2 | 71 | 4 |
| Spellcaster | 281 | 0 | 53 | 28 | 188 | 63 | 62 |
| Thunder | 13 | 0 | 10 | 5 | 77 | 4 | 19 |
| Warrior | 203 | 0 | 363 | 101 | 245 | 53 | 60 |
| Winged Beast | 110 | 0 | 7 | 16 | 15 | 12 | 153 |
| Wyrm | 15 | 0 | 18 | 11 | 23 | 12 | 8 |
| Zombie | 161 | 0 | 38 | 25 | 7 | 7 | 4 |
plt.figure(figsize = (20,5))
sns.heatmap(monster_crosstab.T, annot=True, fmt="g", cmap='viridis', square=True)
plt.show()
monster_crosstab_b = pd.crosstab(formatted_full_df['Monster type'],formatted_full_df['Primary type'], dropna=False)
monster_crosstab_b
| Primary type | Effect Monster | Fusion Monster | Link Monster | Monster Token | Normal Monster | Ritual Monster | Synchro Monster | Xyz Monster |
|---|---|---|---|---|---|---|---|---|
| Monster type | ||||||||
| Aqua | 153 | 11 | 3 | 0 | 59 | 8 | 4 | 17 |
| Beast | 271 | 17 | 9 | 0 | 54 | 1 | 14 | 11 |
| Beast-Warrior | 162 | 11 | 9 | 0 | 21 | 2 | 8 | 23 |
| Creator God | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Cyberse | 122 | 4 | 93 | 0 | 7 | 6 | 5 | 9 |
| Dinosaur | 87 | 7 | 3 | 0 | 18 | 0 | 4 | 3 |
| Divine-Beast | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Dragon | 346 | 62 | 33 | 0 | 46 | 15 | 93 | 60 |
| Fairy | 362 | 21 | 24 | 0 | 36 | 17 | 17 | 32 |
| Fiend | 534 | 46 | 28 | 0 | 79 | 15 | 23 | 40 |
| Fish | 91 | 5 | 1 | 0 | 17 | 1 | 9 | 3 |
| Insect | 180 | 3 | 9 | 0 | 29 | 1 | 7 | 14 |
| Machine | 633 | 47 | 38 | 0 | 67 | 4 | 61 | 65 |
| Plant | 161 | 6 | 15 | 0 | 25 | 0 | 8 | 16 |
| Psychic | 120 | 11 | 5 | 0 | 9 | 0 | 19 | 13 |
| Pyro | 84 | 8 | 1 | 1 | 18 | 0 | 5 | 4 |
| Reptile | 140 | 1 | 3 | 0 | 19 | 0 | 5 | 3 |
| Rock | 169 | 18 | 4 | 0 | 28 | 7 | 5 | 16 |
| Sea Serpent | 55 | 2 | 2 | 0 | 8 | 0 | 5 | 10 |
| Spellcaster | 510 | 25 | 26 | 0 | 55 | 18 | 16 | 25 |
| Thunder | 97 | 8 | 5 | 0 | 11 | 0 | 5 | 2 |
| Warrior | 672 | 94 | 29 | 0 | 80 | 14 | 54 | 82 |
| Winged Beast | 227 | 8 | 10 | 0 | 27 | 4 | 15 | 22 |
| Wyrm | 55 | 2 | 9 | 0 | 3 | 0 | 10 | 8 |
| Zombie | 163 | 7 | 7 | 0 | 30 | 6 | 18 | 11 |
plt.figure(figsize = (20,5))
sns.heatmap(monster_crosstab_b.T, annot=True, fmt="g", cmap='viridis', square=True, norm = LogNorm())
plt.show()
monster_crosstab_c = pd.crosstab(formatted_full_df['Monster type'],formatted_full_df['Secondary type'], dropna=False)
monster_crosstab_c
| Secondary type | Flip monster | Gemini monster | Spirit monster | Toon monster | Tuner monster | Union monster |
|---|---|---|---|---|---|---|
| Monster type | ||||||
| Aqua | 4 | 4 | 1 | 1 | 10 | 3 |
| Beast | 15 | 1 | 2 | 0 | 22 | 0 |
| Beast-Warrior | 1 | 0 | 1 | 0 | 9 | 0 |
| Cyberse | 0 | 0 | 0 | 0 | 6 | 0 |
| Dinosaur | 0 | 0 | 0 | 0 | 7 | 0 |
| Dragon | 1 | 6 | 1 | 3 | 42 | 4 |
| Fairy | 8 | 2 | 7 | 0 | 20 | 5 |
| Fiend | 27 | 4 | 2 | 1 | 41 | 1 |
| Fish | 0 | 1 | 0 | 0 | 8 | 0 |
| Insect | 20 | 2 | 0 | 0 | 12 | 0 |
| Machine | 10 | 1 | 0 | 4 | 80 | 18 |
| Plant | 4 | 1 | 0 | 0 | 20 | 1 |
| Psychic | 3 | 0 | 0 | 0 | 23 | 0 |
| Pyro | 4 | 2 | 2 | 0 | 8 | 1 |
| Reptile | 18 | 1 | 0 | 0 | 7 | 0 |
| Rock | 11 | 1 | 2 | 0 | 3 | 0 |
| Sea Serpent | 1 | 1 | 0 | 0 | 9 | 0 |
| Spellcaster | 33 | 3 | 4 | 4 | 39 | 0 |
| Thunder | 3 | 1 | 1 | 0 | 8 | 0 |
| Warrior | 11 | 9 | 5 | 3 | 30 | 3 |
| Winged Beast | 5 | 2 | 7 | 1 | 30 | 0 |
| Wyrm | 0 | 0 | 0 | 0 | 10 | 0 |
| Zombie | 4 | 3 | 2 | 0 | 22 | 1 |
plt.figure(figsize = (20,5))
sns.heatmap(monster_crosstab_c.T, annot=True, fmt="g", cmap='viridis', square=True, norm = LogNorm())
plt.show()
print('Total number of effect types:', formatted_monster_df['Effect type'].explode().nunique())
Total number of effect types: 14
formatted_monster_df[formatted_monster_df['Effect type'].notna()].drop(columns=['Card type']).explode('Effect type').groupby('Effect type').nunique()
| Name | Password | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Effect type | ||||||||||||||||||
| Activation condition | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 |
| Condition | 3032 | 2954 | 7 | 6 | 7 | 25 | 14 | 63 | 63 | 13 | 5 | 53 | 634 | 3 | 3 | 5 | 6 | 3021 |
| Continuous Effect | 2136 | 2116 | 6 | 5 | 7 | 24 | 14 | 59 | 52 | 12 | 6 | 48 | 555 | 3 | 3 | 4 | 4 | 2133 |
| Continuous-like Effect | 234 | 233 | 6 | 3 | 6 | 21 | 11 | 42 | 36 | 13 | 1 | 2 | 72 | 2 | 3 | 4 | 3 | 234 |
| Flip effect | 169 | 168 | 1 | 1 | 6 | 19 | 12 | 38 | 33 | 1 | 0 | 0 | 43 | 2 | 3 | 3 | 4 | 169 |
| Ignition Effect | 2582 | 2555 | 6 | 6 | 7 | 24 | 13 | 66 | 61 | 12 | 5 | 42 | 632 | 3 | 3 | 5 | 6 | 2575 |
| Ignition-like Effect | 216 | 208 | 6 | 2 | 6 | 20 | 12 | 35 | 32 | 13 | 1 | 1 | 74 | 1 | 3 | 4 | 6 | 216 |
| Lingering effect | 17 | 16 | 2 | 1 | 6 | 12 | 7 | 12 | 14 | 0 | 2 | 2 | 10 | 0 | 0 | 2 | 3 | 17 |
| Maintenance cost | 44 | 44 | 3 | 0 | 6 | 12 | 8 | 21 | 18 | 2 | 1 | 1 | 8 | 0 | 1 | 1 | 1 | 44 |
| Quick Effect | 1004 | 992 | 6 | 4 | 6 | 23 | 13 | 50 | 47 | 9 | 5 | 28 | 387 | 3 | 3 | 4 | 5 | 1002 |
| Quick-like Effect | 4 | 4 | 1 | 0 | 1 | 1 | 1 | 3 | 2 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 4 |
| Summoning condition | 913 | 865 | 6 | 4 | 7 | 25 | 13 | 52 | 51 | 8 | 5 | 6 | 314 | 3 | 3 | 5 | 6 | 909 |
| Trigger Effect | 4283 | 4241 | 7 | 6 | 7 | 24 | 14 | 66 | 62 | 13 | 5 | 49 | 756 | 3 | 3 | 4 | 6 | 4264 |
| Unclassified effect | 808 | 796 | 6 | 5 | 7 | 25 | 13 | 49 | 45 | 9 | 5 | 12 | 272 | 3 | 3 | 4 | 4 | 805 |
monster_effect_colors = card_colors['Effect Monster']
formatted_monster_df['Effect type'].explode('Effect type').value_counts().plot.bar(figsize = (18,6), grid = True, color = monster_effect_colors)
plt.show()
print('Total number of ATK values:', formatted_monster_df['ATK'].nunique())
Total number of ATK values: 82
formatted_monster_df.drop(columns=['Card type']).groupby('ATK').nunique().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce'))
| Name | Password | Primary type | Secondary type | Attribute | Monster type | Level/Rank | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ATK | ||||||||||||||||||
| 0 | 611 | 584 | 8 | 5 | 6 | 23 | 13 | 35 | 9 | 5 | 15 | 92 | 233 | 3 | 3 | 6 | 6 | 610 |
| 50 | 2 | 2 | 1 | 0 | 2 | 2 | 1 | 2 | 0 | 0 | 0 | 2 | 2 | 0 | 0 | 1 | 1 | 2 |
| 100 | 217 | 216 | 5 | 3 | 6 | 20 | 11 | 27 | 8 | 2 | 2 | 48 | 107 | 2 | 3 | 4 | 3 | 217 |
| 150 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
| 200 | 118 | 117 | 6 | 5 | 6 | 20 | 7 | 21 | 4 | 1 | 2 | 34 | 67 | 2 | 3 | 3 | 3 | 118 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4500 | 12 | 12 | 3 | 0 | 3 | 6 | 4 | 4 | 0 | 0 | 0 | 10 | 9 | 1 | 1 | 1 | 1 | 12 |
| 4600 | 2 | 2 | 1 | 0 | 2 | 1 | 1 | 1 | 0 | 0 | 0 | 2 | 1 | 0 | 0 | 1 | 1 | 2 |
| 5000 | 9 | 9 | 5 | 0 | 3 | 4 | 2 | 4 | 0 | 1 | 1 | 8 | 6 | 1 | 1 | 1 | 1 | 9 |
| ? | 83 | 75 | 6 | 1 | 7 | 20 | 15 | 8 | 2 | 1 | 1 | 34 | 36 | 2 | 3 | 4 | 4 | 84 |
| X000 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 |
82 rows × 18 columns
atk_colors = card_colors['Monster Card']
formatted_monster_df['DEF'].value_counts().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce')).plot.bar(figsize = (18,6), grid = True, color = atk_colors)
plt.show()
print('Total number of DEF values:', formatted_monster_df['DEF'].nunique())
Total number of DEF values: 77
formatted_monster_df.drop(columns=['Card type']).groupby('DEF').nunique().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce'))
| Name | Password | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| DEF | ||||||||||||||||||
| 0 | 768 | 737 | 7 | 6 | 6 | 23 | 14 | 45 | 10 | 0 | 0 | 104 | 258 | 3 | 3 | 5 | 5 | 765 |
| 50 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
| 100 | 208 | 207 | 5 | 4 | 6 | 19 | 10 | 24 | 8 | 0 | 0 | 46 | 95 | 2 | 3 | 3 | 4 | 207 |
| 200 | 249 | 246 | 5 | 5 | 6 | 23 | 10 | 31 | 5 | 0 | 0 | 47 | 108 | 3 | 3 | 4 | 5 | 249 |
| 250 | 8 | 8 | 2 | 1 | 4 | 5 | 2 | 4 | 0 | 0 | 0 | 5 | 3 | 0 | 1 | 1 | 1 | 8 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4500 | 2 | 2 | 2 | 0 | 2 | 2 | 1 | 1 | 0 | 0 | 0 | 2 | 1 | 0 | 0 | 1 | 1 | 2 |
| 4800 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
| 5000 | 5 | 5 | 2 | 0 | 3 | 3 | 2 | 2 | 0 | 0 | 0 | 4 | 3 | 1 | 1 | 1 | 1 | 5 |
| ? | 56 | 49 | 5 | 1 | 7 | 17 | 14 | 2 | 1 | 0 | 0 | 25 | 25 | 2 | 3 | 4 | 4 | 57 |
| X000 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 |
77 rows × 18 columns
def_colors = card_colors['Monster Card']
formatted_monster_df['DEF'].value_counts().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce')).plot.bar(figsize = (18,6), grid = True, color = def_colors)
plt.show()
formatted_monster_df.drop(columns=['Card type', 'Link', 'Link Arrows']).groupby('Level/Rank').nunique().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce'))
| Name | Password | Primary type | Secondary type | Attribute | Monster type | ATK | DEF | Pendulum Scale | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Level/Rank | ||||||||||||||||
| 0 | 6 | 6 | 2 | 0 | 2 | 2 | 3 | 3 | 0 | 5 | 3 | 0 | 0 | 2 | 2 | 6 |
| 1 | 627 | 601 | 7 | 5 | 6 | 23 | 22 | 29 | 10 | 80 | 227 | 3 | 3 | 5 | 5 | 625 |
| 2 | 672 | 662 | 6 | 5 | 6 | 23 | 29 | 30 | 7 | 74 | 213 | 3 | 3 | 5 | 6 | 671 |
| 3 | 1144 | 1136 | 6 | 5 | 6 | 23 | 41 | 36 | 9 | 92 | 290 | 3 | 3 | 5 | 7 | 1144 |
| 4 | 2326 | 2312 | 6 | 6 | 6 | 23 | 54 | 47 | 9 | 134 | 505 | 3 | 3 | 5 | 7 | 2319 |
| 5 | 593 | 591 | 6 | 6 | 6 | 23 | 46 | 38 | 8 | 83 | 234 | 3 | 3 | 4 | 4 | 593 |
| 6 | 606 | 597 | 6 | 6 | 6 | 23 | 38 | 38 | 9 | 92 | 233 | 3 | 3 | 6 | 6 | 607 |
| 7 | 467 | 457 | 6 | 6 | 6 | 23 | 38 | 35 | 9 | 100 | 225 | 3 | 3 | 5 | 6 | 468 |
| 8 | 671 | 648 | 6 | 5 | 6 | 23 | 42 | 41 | 8 | 111 | 298 | 3 | 3 | 5 | 6 | 672 |
| 9 | 143 | 138 | 5 | 2 | 6 | 21 | 31 | 27 | 1 | 55 | 85 | 1 | 3 | 5 | 4 | 143 |
| 10 | 245 | 232 | 5 | 2 | 7 | 22 | 32 | 33 | 6 | 76 | 146 | 2 | 3 | 4 | 4 | 248 |
| 11 | 31 | 30 | 6 | 2 | 6 | 13 | 16 | 17 | 1 | 22 | 23 | 0 | 1 | 3 | 2 | 31 |
| 12 | 51 | 48 | 5 | 1 | 6 | 12 | 12 | 16 | 2 | 32 | 38 | 1 | 2 | 2 | 3 | 51 |
| 13 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
| ? | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
stars_colors = card_colors['Level']
formatted_monster_df['Level/Rank'].value_counts().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce')).plot.bar(figsize = (18,6), grid = True, rot=0, color= stars_colors)
plt.show()
formatted_monster_df[['Level/Rank','ATK']].apply(pd.to_numeric, errors = 'coerce').dropna().astype(int).groupby('Level/Rank').describe()
| ATK | ||||||||
|---|---|---|---|---|---|---|---|---|
| count | mean | std | min | 25% | 50% | 75% | max | |
| Level/Rank | ||||||||
| 0 | 5.0 | 600.000000 | 1341.640786 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
| 1 | 617.0 | 239.789303 | 352.151718 | 0.0 | 0.0 | 100.0 | 300.0 | 2500.0 |
| 2 | 670.0 | 581.716418 | 409.369938 | 0.0 | 300.0 | 500.0 | 800.0 | 2400.0 |
| 3 | 1141.0 | 959.027169 | 485.041163 | 0.0 | 600.0 | 1000.0 | 1300.0 | 3000.0 |
| 4 | 2314.0 | 1418.725151 | 539.719843 | 0.0 | 1200.0 | 1500.0 | 1800.0 | 3000.0 |
| 5 | 590.0 | 1765.711864 | 637.542570 | 0.0 | 1500.0 | 1900.0 | 2200.0 | 4000.0 |
| 6 | 603.0 | 2015.174129 | 613.522395 | 0.0 | 1900.0 | 2200.0 | 2400.0 | 4000.0 |
| 7 | 463.0 | 2284.773218 | 619.488951 | 0.0 | 2200.0 | 2500.0 | 2600.0 | 3300.0 |
| 8 | 663.0 | 2548.340875 | 706.682791 | 0.0 | 2500.0 | 2800.0 | 3000.0 | 4500.0 |
| 9 | 140.0 | 2601.785714 | 842.196740 | 0.0 | 2500.0 | 2800.0 | 3000.0 | 4500.0 |
| 10 | 225.0 | 2825.111111 | 1216.938896 | 0.0 | 2800.0 | 3000.0 | 3500.0 | 5000.0 |
| 11 | 30.0 | 2990.000000 | 1093.113238 | 0.0 | 3000.0 | 3350.0 | 3500.0 | 4000.0 |
| 12 | 47.0 | 3361.702128 | 1402.723003 | 0.0 | 3000.0 | 4000.0 | 4000.0 | 5000.0 |
formatted_monster_df[['Level/Rank','DEF']].apply(pd.to_numeric, errors = 'coerce').dropna().astype(int).groupby('Level/Rank').describe()
| DEF | ||||||||
|---|---|---|---|---|---|---|---|---|
| count | mean | std | min | 25% | 50% | 75% | max | |
| Level/Rank | ||||||||
| 0 | 5.0 | 400.000000 | 894.427191 | 0.0 | 0.0 | 0.0 | 0.0 | 2000.0 |
| 1 | 619.0 | 337.883683 | 519.434793 | 0.0 | 0.0 | 100.0 | 400.0 | 2500.0 |
| 2 | 671.0 | 660.506706 | 555.062761 | 0.0 | 200.0 | 500.0 | 900.0 | 2400.0 |
| 3 | 1141.0 | 955.740578 | 571.578224 | 0.0 | 600.0 | 900.0 | 1300.0 | 3000.0 |
| 4 | 2316.0 | 1169.054404 | 606.786682 | 0.0 | 800.0 | 1200.0 | 1600.0 | 3000.0 |
| 5 | 591.0 | 1423.688663 | 673.001321 | 0.0 | 1000.0 | 1500.0 | 1900.0 | 3000.0 |
| 6 | 603.0 | 1556.268657 | 711.873323 | 0.0 | 1200.0 | 1700.0 | 2000.0 | 3000.0 |
| 7 | 465.0 | 1886.666667 | 653.772760 | 0.0 | 1600.0 | 2000.0 | 2300.0 | 3300.0 |
| 8 | 670.0 | 1976.268657 | 848.089977 | 0.0 | 1600.0 | 2100.0 | 2500.0 | 4000.0 |
| 9 | 140.0 | 2315.357143 | 790.134685 | 0.0 | 2000.0 | 2500.0 | 2925.0 | 3700.0 |
| 10 | 234.0 | 2227.564103 | 1279.912000 | 0.0 | 1825.0 | 2500.0 | 3000.0 | 5000.0 |
| 11 | 30.0 | 2661.666667 | 1169.415071 | 0.0 | 2125.0 | 3000.0 | 3400.0 | 4000.0 |
| 12 | 48.0 | 2879.166667 | 1644.586003 | 0.0 | 2000.0 | 3350.0 | 4000.0 | 5000.0 |
formatted_monster_df.drop(columns=['Card type', 'Link', 'Link Arrows']).groupby('Pendulum Scale').nunique().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce'))
| Name | Password | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | DEF | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Pendulum Scale | ||||||||||||||||
| 0 | 10 | 10 | 2 | 1 | 5 | 7 | 6 | 5 | 5 | 8 | 8 | 1 | 0 | 1 | 1 | 10 |
| 1 | 68 | 64 | 5 | 2 | 6 | 10 | 11 | 28 | 26 | 37 | 39 | 0 | 1 | 4 | 5 | 68 |
| 2 | 36 | 36 | 2 | 1 | 6 | 11 | 6 | 17 | 22 | 21 | 15 | 0 | 2 | 4 | 2 | 36 |
| 3 | 36 | 36 | 2 | 1 | 6 | 15 | 8 | 22 | 15 | 23 | 17 | 0 | 0 | 1 | 1 | 36 |
| 4 | 32 | 32 | 5 | 0 | 5 | 8 | 8 | 18 | 16 | 25 | 16 | 1 | 1 | 1 | 1 | 32 |
| 5 | 34 | 34 | 2 | 1 | 6 | 12 | 7 | 23 | 21 | 20 | 16 | 0 | 1 | 3 | 3 | 34 |
| 6 | 15 | 15 | 1 | 1 | 4 | 7 | 6 | 11 | 11 | 11 | 9 | 0 | 0 | 2 | 1 | 15 |
| 7 | 27 | 27 | 2 | 1 | 6 | 14 | 6 | 19 | 17 | 14 | 16 | 0 | 2 | 2 | 1 | 27 |
| 8 | 40 | 39 | 5 | 1 | 6 | 9 | 8 | 19 | 18 | 23 | 21 | 0 | 0 | 1 | 4 | 40 |
| 9 | 8 | 8 | 2 | 1 | 3 | 3 | 5 | 3 | 2 | 5 | 3 | 0 | 0 | 2 | 1 | 8 |
| 10 | 14 | 11 | 5 | 0 | 6 | 6 | 5 | 6 | 8 | 11 | 8 | 0 | 0 | 2 | 2 | 14 |
| 12 | 3 | 2 | 2 | 0 | 2 | 3 | 2 | 3 | 3 | 3 | 3 | 0 | 0 | 1 | 2 | 3 |
| 13 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
scales_colors = card_colors['Pendulum Monster']
formatted_monster_df['Pendulum Scale'].value_counts().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce')).plot.bar(figsize = (18,6), grid = True, rot=0, color = scales_colors)
plt.show()
formatted_monster_df[['Pendulum Scale','ATK']].apply(pd.to_numeric, errors = 'coerce').dropna().astype(int).groupby('Pendulum Scale').describe()
| ATK | ||||||||
|---|---|---|---|---|---|---|---|---|
| count | mean | std | min | 25% | 50% | 75% | max | |
| Pendulum Scale | ||||||||
| 0 | 10.0 | 1390.000000 | 1317.784336 | 0.0 | 0.0 | 1450.0 | 2500.0 | 3000.0 |
| 1 | 67.0 | 1747.761194 | 1045.822601 | 0.0 | 1000.0 | 1800.0 | 2500.0 | 4000.0 |
| 2 | 36.0 | 1423.611111 | 688.734462 | 100.0 | 800.0 | 1500.0 | 2000.0 | 2500.0 |
| 3 | 36.0 | 1437.500000 | 845.354955 | 0.0 | 600.0 | 1725.0 | 2025.0 | 2600.0 |
| 4 | 32.0 | 1787.500000 | 1011.785391 | 0.0 | 1100.0 | 2000.0 | 2550.0 | 3000.0 |
| 5 | 34.0 | 1339.705882 | 808.831875 | 0.0 | 850.0 | 1325.0 | 1800.0 | 3450.0 |
| 6 | 15.0 | 1320.000000 | 707.308783 | 100.0 | 950.0 | 1500.0 | 1800.0 | 2400.0 |
| 7 | 27.0 | 1279.629630 | 787.920737 | 0.0 | 700.0 | 1400.0 | 1750.0 | 3000.0 |
| 8 | 40.0 | 1232.500000 | 957.129121 | 0.0 | 300.0 | 1200.0 | 2000.0 | 3300.0 |
| 9 | 8.0 | 2150.000000 | 730.948503 | 1000.0 | 2050.0 | 2400.0 | 2500.0 | 2800.0 |
| 10 | 14.0 | 1678.571429 | 1376.829452 | 0.0 | 125.0 | 2500.0 | 2875.0 | 3000.0 |
| 12 | 2.0 | 1550.000000 | 2050.609665 | 100.0 | 825.0 | 1550.0 | 2275.0 | 3000.0 |
| 13 | 1.0 | 0.000000 | NaN | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
formatted_monster_df[['Pendulum Scale','DEF']].apply(pd.to_numeric, errors = 'coerce').dropna().astype(int).groupby('Pendulum Scale').describe()
| DEF | ||||||||
|---|---|---|---|---|---|---|---|---|
| count | mean | std | min | 25% | 50% | 75% | max | |
| Pendulum Scale | ||||||||
| 0 | 10.0 | 1200.000000 | 1273.664878 | 0.0 | 0.0 | 750.0 | 2500.0 | 3000.0 |
| 1 | 68.0 | 1592.647059 | 949.204880 | 0.0 | 975.0 | 1750.0 | 2400.0 | 4000.0 |
| 2 | 36.0 | 1338.888889 | 728.316171 | 0.0 | 875.0 | 1200.0 | 1825.0 | 2700.0 |
| 3 | 36.0 | 1165.277778 | 788.834533 | 0.0 | 575.0 | 1200.0 | 1800.0 | 3000.0 |
| 4 | 32.0 | 1534.375000 | 830.316448 | 0.0 | 1000.0 | 1600.0 | 2075.0 | 2800.0 |
| 5 | 34.0 | 1136.764706 | 822.625953 | 0.0 | 550.0 | 1000.0 | 1575.0 | 3000.0 |
| 6 | 15.0 | 1226.666667 | 711.604492 | 400.0 | 600.0 | 1100.0 | 1700.0 | 2600.0 |
| 7 | 27.0 | 1312.962963 | 830.383669 | 0.0 | 700.0 | 1300.0 | 2000.0 | 2700.0 |
| 8 | 40.0 | 1027.500000 | 783.479255 | 0.0 | 375.0 | 1000.0 | 1700.0 | 2700.0 |
| 9 | 8.0 | 1225.000000 | 636.396103 | 1000.0 | 1000.0 | 1000.0 | 1000.0 | 2800.0 |
| 10 | 14.0 | 1850.000000 | 1124.380171 | 0.0 | 750.0 | 2500.0 | 2575.0 | 3000.0 |
| 12 | 2.0 | 1550.000000 | 2050.609665 | 100.0 | 825.0 | 1550.0 | 2275.0 | 3000.0 |
| 13 | 1.0 | 0.000000 | NaN | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
formatted_monster_df[['Pendulum Scale','Level/Rank']].apply(pd.to_numeric, errors = 'coerce').dropna().astype(int).groupby('Pendulum Scale').describe()
| Level/Rank | ||||||||
|---|---|---|---|---|---|---|---|---|
| count | mean | std | min | 25% | 50% | 75% | max | |
| Pendulum Scale | ||||||||
| 0 | 10.0 | 6.100000 | 3.348300 | 1.0 | 3.75 | 7.0 | 8.00 | 10.0 |
| 1 | 68.0 | 5.985294 | 2.421870 | 1.0 | 4.00 | 6.0 | 8.00 | 12.0 |
| 2 | 36.0 | 4.416667 | 1.380993 | 1.0 | 3.75 | 4.0 | 5.00 | 7.0 |
| 3 | 36.0 | 4.444444 | 1.731134 | 1.0 | 4.00 | 4.0 | 5.00 | 10.0 |
| 4 | 32.0 | 5.562500 | 2.154328 | 1.0 | 4.00 | 6.0 | 7.00 | 8.0 |
| 5 | 34.0 | 4.176471 | 1.961301 | 1.0 | 3.00 | 4.0 | 4.00 | 11.0 |
| 6 | 15.0 | 3.933333 | 1.579632 | 1.0 | 3.00 | 4.0 | 4.50 | 8.0 |
| 7 | 27.0 | 4.185185 | 1.641693 | 2.0 | 3.00 | 4.0 | 5.00 | 10.0 |
| 8 | 40.0 | 3.925000 | 2.324755 | 1.0 | 2.00 | 4.0 | 6.00 | 10.0 |
| 9 | 8.0 | 5.625000 | 1.302470 | 4.0 | 5.00 | 5.0 | 6.25 | 8.0 |
| 10 | 14.0 | 6.714286 | 2.812843 | 1.0 | 7.00 | 7.0 | 7.75 | 10.0 |
| 12 | 3.0 | 8.333333 | 6.350853 | 1.0 | 6.50 | 12.0 | 12.00 | 12.0 |
| 13 | 1.0 | 7.000000 | NaN | 7.0 | 7.00 | 7.0 | 7.00 | 7.0 |
formatted_monster_df.drop(columns=['Card type', 'Primary type', 'Secondary type','Level/Rank','DEF','Pendulum Scale']).groupby('Link').nunique().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce'))
| Name | Password | Attribute | Monster type | ATK | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Link | |||||||||||||
| 1 | 47 | 47 | 6 | 11 | 10 | 8 | 17 | 26 | 1 | 0 | 3 | 3 | 47 |
| 2 | 184 | 183 | 6 | 23 | 23 | 19 | 31 | 102 | 1 | 2 | 3 | 4 | 184 |
| 3 | 81 | 81 | 6 | 16 | 17 | 17 | 25 | 46 | 2 | 1 | 2 | 2 | 81 |
| 4 | 44 | 41 | 6 | 16 | 12 | 13 | 21 | 24 | 2 | 0 | 4 | 4 | 44 |
| 5 | 9 | 5 | 2 | 5 | 4 | 3 | 6 | 5 | 0 | 0 | 2 | 3 | 9 |
| 6 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
link_colors = card_colors['Link Monster']
formatted_monster_df['Link'].value_counts().sort_index(key=lambda x: pd.to_numeric(x, errors = 'coerce')).plot.bar(figsize = (18,6), grid = True, rot=0, color = link_colors)
plt.show()
formatted_monster_df[['Link','ATK']].apply(pd.to_numeric, errors = 'coerce').dropna().astype(int).groupby('Link').describe()
| ATK | ||||||||
|---|---|---|---|---|---|---|---|---|
| count | mean | std | min | 25% | 50% | 75% | max | |
| Link | ||||||||
| 1 | 47.0 | 736.170213 | 482.937358 | 0.0 | 400.0 | 800.0 | 1000.0 | 1500.0 |
| 2 | 184.0 | 1400.815217 | 508.170283 | 0.0 | 1100.0 | 1500.0 | 1800.0 | 2300.0 |
| 3 | 81.0 | 2258.641975 | 659.487970 | 0.0 | 2200.0 | 2400.0 | 2500.0 | 4000.0 |
| 4 | 43.0 | 2660.465116 | 653.976676 | 0.0 | 2500.0 | 2800.0 | 3000.0 | 3300.0 |
| 5 | 9.0 | 3277.777778 | 712.000312 | 2500.0 | 3000.0 | 3000.0 | 3500.0 | 5000.0 |
| 6 | 1.0 | 0.000000 | NaN | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
print('Total number of link arrow combinations:', formatted_monster_df['Link Arrows'].nunique())
Total number of link arrow combinations: 61
formatted_monster_df.drop(columns=['Card type', 'Primary type', 'Level/Rank', 'Pendulum Scale', 'Link', 'Secondary type', 'DEF']).groupby('Link Arrows').nunique()
| Name | Password | Attribute | Monster type | ATK | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Link Arrows | ||||||||||||
| (←,) | 5 | 5 | 2 | 3 | 2 | 4 | 4 | 0 | 0 | 3 | 2 | 5 |
| (←, ↑) | 4 | 4 | 2 | 3 | 4 | 3 | 2 | 0 | 0 | 1 | 1 | 4 |
| (←, →) | 18 | 18 | 6 | 8 | 11 | 8 | 9 | 0 | 0 | 2 | 2 | 18 |
| (←, →, ↑) | 7 | 7 | 3 | 5 | 6 | 6 | 5 | 0 | 0 | 1 | 1 | 7 |
| (↑,) | 10 | 10 | 5 | 5 | 6 | 9 | 5 | 0 | 0 | 1 | 1 | 10 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| (↙, ↘, ←, ↖) | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
| (↙, ↘, ↑) | 22 | 22 | 6 | 11 | 11 | 11 | 15 | 1 | 1 | 2 | 2 | 22 |
| (↙, ↘, →) | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 0 | 1 | 1 | 2 |
| (↙, ↘, ↖) | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 0 | 0 | 1 | 1 | 2 |
| (↙, ↘, ↖, ↗) | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
61 rows × 12 columns
arrows_colors = card_colors['Link Monster']
formatted_monster_df['Link Arrows'].value_counts().plot.bar(figsize = (18,6), logy=True, grid = True, color = arrows_colors)
plt.show()
formatted_monster_df[formatted_monster_df['Link Arrows'].notna()].drop(columns=['Card type', 'Primary type', 'Level/Rank', 'Pendulum Scale', 'Secondary type', 'DEF']).explode('Link Arrows').groupby('Link Arrows').nunique()
| Name | Password | Attribute | Monster type | ATK | Link | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Link Arrows | |||||||||||||
| ← | 114 | 107 | 6 | 21 | 29 | 6 | 34 | 45 | 2 | 0 | 5 | 4 | 114 |
| ↑ | 114 | 111 | 6 | 19 | 27 | 6 | 31 | 44 | 2 | 1 | 4 | 4 | 114 |
| → | 100 | 93 | 6 | 19 | 27 | 6 | 29 | 40 | 2 | 0 | 4 | 4 | 100 |
| ↓ | 157 | 150 | 6 | 20 | 31 | 6 | 41 | 68 | 3 | 0 | 4 | 5 | 157 |
| ↖ | 10 | 10 | 5 | 5 | 9 | 4 | 6 | 5 | 1 | 0 | 1 | 2 | 10 |
| ↗ | 15 | 15 | 5 | 7 | 10 | 5 | 7 | 7 | 0 | 0 | 2 | 2 | 15 |
| ↘ | 186 | 181 | 6 | 22 | 32 | 6 | 35 | 103 | 3 | 2 | 4 | 5 | 186 |
| ↙ | 189 | 184 | 6 | 22 | 33 | 6 | 37 | 104 | 3 | 2 | 4 | 5 | 189 |
arrows_colors_b = card_colors['Link Monster']
formatted_monster_df['Link Arrows'].explode('Link Arrows').value_counts().plot.bar(figsize = (18,6), grid = True, color = arrows_colors_b)
plt.show()
arrow_per_link = formatted_monster_df[['Link Arrows','Link']].explode('Link Arrows').dropna()
arrow_crosstab = pd.crosstab(arrow_per_link['Link Arrows'],arrow_per_link['Link'])
arrow_crosstab
| Link | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| Link Arrows | ||||||
| ← | 5 | 47 | 23 | 30 | 8 | 1 |
| ↑ | 10 | 28 | 43 | 28 | 4 | 1 |
| → | 2 | 33 | 24 | 31 | 9 | 1 |
| ↓ | 18 | 59 | 41 | 32 | 6 | 1 |
| ↖ | 1 | 2 | 5 | 2 | 0 | 0 |
| ↗ | 3 | 5 | 3 | 3 | 1 | 0 |
| ↘ | 3 | 95 | 53 | 25 | 9 | 1 |
| ↙ | 5 | 99 | 51 | 25 | 8 | 1 |
plt.figure(figsize = (10,6))
sns.heatmap(arrow_crosstab.T, annot=True, fmt="g", cmap='viridis', square=True, norm=LogNorm())
plt.show()
print('Total number of properties:', formatted_st_df['Property'].nunique())
Total number of properties: 9
formatted_st_df.drop(columns=['Card type']).groupby('Property').nunique()
| Name | Password | Effect type | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|
| Property | |||||||||
| Continuous Spell Card | 418 | 412 | 53 | 158 | 3 | 3 | 6 | 5 | 416 |
| Continuous Trap Card | 488 | 479 | 63 | 161 | 2 | 3 | 4 | 2 | 488 |
| Counter Trap Card | 154 | 152 | 19 | 58 | 2 | 2 | 3 | 2 | 154 |
| Equip Spell Card | 262 | 262 | 37 | 74 | 1 | 3 | 3 | 2 | 262 |
| Field Spell Card | 272 | 266 | 35 | 144 | 2 | 3 | 5 | 4 | 273 |
| Normal Spell Card | 911 | 902 | 43 | 228 | 3 | 3 | 5 | 6 | 910 |
| Normal Trap Card | 1158 | 1148 | 48 | 238 | 3 | 2 | 5 | 6 | 1154 |
| Quick-Play Spell Card | 422 | 415 | 34 | 139 | 3 | 3 | 3 | 4 | 421 |
| Ritual Spell Card | 75 | 74 | 8 | 25 | 2 | 2 | 2 | 2 | 75 |
st_colors = [card_colors[i] for i in formatted_full_df[['Card type','Property']].value_counts().index.get_level_values(0)]
formatted_st_df['Property'].value_counts().plot.bar(figsize = (18,6), grid = True, rot=45, color = st_colors)
plt.show()
print('Total number of effect types:', formatted_st_df['Effect type'].explode().nunique())
Total number of effect types: 14
formatted_st_df.explode('Effect type').groupby('Effect type').nunique()
| Name | Password | Card type | Property | Archseries | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|
| Effect type | ||||||||||
| Activation condition | 832 | 825 | 2 | 8 | 171 | 3 | 3 | 5 | 5 | 831 |
| Condition | 1655 | 1622 | 2 | 9 | 368 | 3 | 3 | 6 | 5 | 1645 |
| Continuous Effect | 21 | 21 | 2 | 6 | 12 | 0 | 2 | 1 | 1 | 21 |
| Continuous-like Effect | 893 | 883 | 2 | 7 | 236 | 3 | 3 | 6 | 5 | 893 |
| Cost | 452 | 450 | 2 | 7 | 112 | 3 | 3 | 5 | 4 | 452 |
| Effect | 2908 | 2872 | 2 | 9 | 426 | 3 | 3 | 6 | 6 | 2895 |
| Ignition Effect | 2 | 2 | 2 | 2 | 2 | 0 | 0 | 1 | 1 | 2 |
| Ignition-like Effect | 431 | 425 | 1 | 6 | 180 | 1 | 2 | 4 | 5 | 430 |
| Lingering effect | 94 | 94 | 2 | 6 | 41 | 2 | 2 | 3 | 3 | 94 |
| Maintenance cost | 22 | 22 | 2 | 5 | 7 | 1 | 1 | 3 | 2 | 22 |
| Quick Effect | 9 | 9 | 2 | 3 | 4 | 0 | 0 | 1 | 1 | 9 |
| Quick-like Effect | 332 | 326 | 2 | 4 | 147 | 2 | 1 | 4 | 5 | 332 |
| Trigger Effect | 840 | 824 | 2 | 9 | 257 | 2 | 3 | 4 | 5 | 834 |
| Unclassified effect | 83 | 83 | 2 | 9 | 48 | 1 | 0 | 2 | 2 | 82 |
spell = formatted_spell_df['Effect type'].explode('Effect type').value_counts().rename('Spell Card')
trap = formatted_trap_df['Effect type'].explode('Effect type').value_counts().rename('Trap Card')
st_diff = pd.concat([spell, trap], axis = 1)
st_diff
| Spell Card | Trap Card | |
|---|---|---|
| Effect | 1514 | 1395.0 |
| Condition | 1123 | 533.0 |
| Continuous-like Effect | 614 | 280.0 |
| Trigger Effect | 564 | 276.0 |
| Ignition-like Effect | 431 | NaN |
| Activation condition | 244 | 588.0 |
| Cost | 241 | 211.0 |
| Unclassified effect | 63 | 20.0 |
| Lingering effect | 56 | 38.0 |
| Maintenance cost | 11 | 11.0 |
| Continuous Effect | 7 | 14.0 |
| Quick Effect | 4 | 5.0 |
| Quick-like Effect | 3 | 329.0 |
| Ignition Effect | 1 | 1.0 |
st_diff_colors = {'Spell Card': card_colors['Spell Card'], 'Trap Card': card_colors['Trap Card']}
st_diff.plot.bar(figsize = (18,6), stacked = True, grid = True, rot=45, color = st_diff_colors)
plt.show()
exploded_archseries = formatted_full_df.explode('Archseries')
print('Total number of Archseries:', exploded_archseries['Archseries'].nunique())
Total number of Archseries: 710
exploded_archseries.groupby('Archseries').nunique()
| Name | Password | Card type | Property | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Artwork | Errata | TCG status | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Archseries | ||||||||||||||||||||
| "C" | 9 | 8 | 1 | 0 | 2 | 0 | 1 | 1 | 8 | 9 | 8 | 0 | 0 | 0 | 7 | 0 | 1 | 2 | 2 | 9 |
| -Eyes Dragon | 72 | 71 | 1 | 0 | 7 | 2 | 6 | 3 | 10 | 16 | 13 | 6 | 1 | 1 | 44 | 1 | 3 | 2 | 3 | 71 |
| /Assault Mode | 7 | 7 | 1 | 0 | 1 | 0 | 5 | 6 | 5 | 6 | 6 | 0 | 0 | 0 | 5 | 0 | 0 | 1 | 1 | 7 |
| @Ignister | 18 | 18 | 1 | 0 | 6 | 1 | 6 | 1 | 7 | 10 | 9 | 0 | 3 | 4 | 9 | 0 | 0 | 1 | 1 | 18 |
| A-to-Z | 16 | 16 | 1 | 0 | 3 | 1 | 1 | 1 | 4 | 13 | 12 | 0 | 0 | 0 | 5 | 2 | 3 | 1 | 2 | 16 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| sphinx | 10 | 10 | 2 | 1 | 1 | 0 | 2 | 2 | 4 | 8 | 5 | 0 | 0 | 0 | 9 | 0 | 0 | 1 | 1 | 10 |
| sprout | 2 | 2 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 1 | 1 | 2 |
| tellarknight | 21 | 21 | 2 | 3 | 2 | 0 | 2 | 3 | 2 | 16 | 14 | 2 | 0 | 0 | 11 | 0 | 0 | 2 | 2 | 21 |
| with Chain | 4 | 4 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 1 | 0 | 1 | 1 | 4 |
| with Eyes of Blue | 8 | 8 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 3 | 4 | 0 | 0 | 0 | 6 | 0 | 1 | 1 | 1 | 8 |
710 rows × 20 columns
exploded_archseries['Archseries'].value_counts().plot.barh(figsize = (10,200), grid = True)
plt.show()
archseries_crosstab = pd.crosstab(exploded_archseries['Archseries'],exploded_archseries['Card type'], margins = True)
archseries_crosstab
| Card type | Monster Card | Spell Card | Trap Card | All |
|---|---|---|---|---|
| Archseries | ||||
| "C" | 9 | 0 | 0 | 9 |
| -Eyes Dragon | 72 | 0 | 0 | 72 |
| /Assault Mode | 7 | 0 | 0 | 7 |
| @Ignister | 18 | 0 | 0 | 18 |
| A-to-Z | 16 | 0 | 0 | 16 |
| ... | ... | ... | ... | ... |
| sprout | 2 | 0 | 0 | 2 |
| tellarknight | 17 | 4 | 0 | 21 |
| with Chain | 0 | 0 | 4 | 4 |
| with Eyes of Blue | 5 | 3 | 0 | 8 |
| All | 7263 | 1351 | 891 | 9505 |
711 rows × 4 columns
archseries_crosstab_b = pd.crosstab(exploded_archseries['Archseries'],exploded_archseries['Primary type'], margins = True)
archseries_crosstab_b
| Primary type | Effect Monster | Fusion Monster | Link Monster | Monster Token | Normal Monster | Ritual Monster | Synchro Monster | Xyz Monster | All |
|---|---|---|---|---|---|---|---|---|---|
| Archseries | |||||||||
| "C" | 8 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 9 |
| -Eyes Dragon | 31 | 11 | 1 | 0 | 3 | 4 | 5 | 17 | 72 |
| /Assault Mode | 7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 7 |
| @Ignister | 10 | 1 | 4 | 0 | 0 | 1 | 1 | 1 | 18 |
| A-to-Z | 6 | 8 | 0 | 0 | 2 | 0 | 0 | 0 | 16 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| sphinx | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 9 |
| sprout | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 |
| tellarknight | 12 | 0 | 0 | 0 | 0 | 0 | 0 | 5 | 17 |
| with Eyes of Blue | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 5 |
| All | 4661 | 532 | 333 | 1 | 244 | 120 | 437 | 931 | 7259 |
647 rows × 9 columns
archseries_crosstab_c = pd.crosstab(exploded_archseries['Archseries'],exploded_archseries['Secondary type'], margins = True)
archseries_crosstab_c
| Secondary type | Flip monster | Gemini monster | Spirit monster | Toon monster | Tuner monster | Union monster | All |
|---|---|---|---|---|---|---|---|
| Archseries | |||||||
| -Eyes Dragon | 0 | 2 | 0 | 2 | 0 | 0 | 4 |
| @Ignister | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| A-to-Z | 0 | 0 | 0 | 0 | 0 | 6 | 6 |
| Adamancipator | 0 | 0 | 0 | 0 | 3 | 0 | 3 |
| Alien | 1 | 1 | 0 | 0 | 1 | 0 | 3 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| itsu | 0 | 0 | 0 | 0 | 0 | 2 | 2 |
| lswarm | 2 | 0 | 0 | 0 | 0 | 0 | 2 |
| roid | 0 | 0 | 0 | 0 | 9 | 0 | 9 |
| with Eyes of Blue | 0 | 0 | 0 | 0 | 5 | 0 | 5 |
| All | 126 | 28 | 13 | 36 | 415 | 18 | 636 |
196 rows × 7 columns
archseries_crosstab_d = pd.crosstab(exploded_archseries['Archseries'],exploded_archseries['Monster type'], margins = True)
archseries_crosstab_d
| Monster type | Aqua | Beast | Beast-Warrior | Creator God | Cyberse | Dinosaur | Divine-Beast | Dragon | Fairy | Fiend | ... | Reptile | Rock | Sea Serpent | Spellcaster | Thunder | Warrior | Winged Beast | Wyrm | Zombie | All |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Archseries | |||||||||||||||||||||
| "C" | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 9 |
| -Eyes Dragon | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 67 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 72 |
| /Assault Mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | ... | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 7 |
| @Ignister | 0 | 0 | 0 | 0 | 18 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 18 |
| A-to-Z | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 16 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| sphinx | 0 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 9 |
| sprout | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 |
| tellarknight | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | ... | 0 | 0 | 0 | 0 | 0 | 15 | 0 | 1 | 0 | 17 |
| with Eyes of Blue | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 5 | 0 | 0 | 0 | 0 | 0 | 5 |
| All | 194 | 294 | 185 | 2 | 149 | 81 | 12 | 718 | 445 | 698 | ... | 138 | 214 | 71 | 578 | 95 | 1241 | 268 | 77 | 158 | 7263 |
647 rows × 26 columns
archseries_crosstab_e = pd.crosstab(exploded_archseries['Archseries'],exploded_archseries['Property'], margins = True)
archseries_crosstab_e
| Property | Continuous Spell Card | Continuous Trap Card | Counter Trap Card | Equip Spell Card | Field Spell Card | Normal Spell Card | Normal Trap Card | Quick-Play Spell Card | Ritual Spell Card | All |
|---|---|---|---|---|---|---|---|---|---|---|
| Archseries | ||||||||||
| A.I. | 1 | 3 | 0 | 0 | 1 | 4 | 1 | 2 | 1 | 13 |
| Abyss Actor | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 0 | 0 | 3 |
| Abyss Script | 1 | 0 | 0 | 0 | 0 | 5 | 0 | 1 | 0 | 7 |
| Abyss- | 0 | 1 | 0 | 3 | 0 | 0 | 3 | 0 | 0 | 7 |
| Adamancipator | 0 | 0 | 1 | 0 | 1 | 2 | 1 | 0 | 0 | 5 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| sphinx | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| tellarknight | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 2 | 0 | 4 |
| with Chain | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 0 | 0 | 4 |
| with Eyes of Blue | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 3 |
| All | 241 | 287 | 72 | 130 | 181 | 506 | 532 | 255 | 38 | 2242 |
396 rows × 10 columns
print('Total number of cards with edited or alternate artworks:', formatted_full_df['Artwork'].count())
Total number of cards with edited or alternate artworks: 426
formatted_full_df[['Name','Password','TCG status','OCG status','Artwork']][formatted_full_df['Artwork'].notna()]
| Name | Password | TCG status | OCG status | Artwork | |
|---|---|---|---|---|---|
| 53 | Alluring Mirror Split | 92881099 | Unlimited | Unlimited | (Alternate, Edited) |
| 62 | Amazoness Spellcaster | 81325903 | Unlimited | Unlimited | (Edited,) |
| 71 | Ancient Gear Castle | 92001300 | Unlimited | Unlimited | (Edited,) |
| 117 | Arrivalrivals | 29508346 | Unlimited | Unlimited | (Alternate, Edited) |
| 136 | Axe of Despair | 40619825 | Unlimited | Unlimited | (Edited,) |
| ... | ... | ... | ... | ... | ... |
| 11940 | Soitsu | 60246171 | Unlimited | Unlimited | (Edited,) |
| 11991 | Stardust Dragon | 44508094 | Unlimited | Unlimited | (Alternate,) |
| 11999 | Storming Wynn | 29013526 | Unlimited | Unlimited | (Alternate, Edited) |
| 12026 | Thousand Dragon | 41462083 | Unlimited | Unlimited | (Alternate,) |
| 12028 | Toon Harpie Lady | 64116319 | Unlimited | Unlimited | (Edited,) |
426 rows × 5 columns
artwork_value_counts = formatted_full_df['Artwork'].value_counts()
plt.figure(figsize=(20,8))
venn2(subsets = (artwork_value_counts[('Alternate',)], artwork_value_counts[('Edited',)],artwork_value_counts[('Alternate','Edited')]), set_labels = ('Alternate artwork', 'Edited artwork'))
plt.show()
artwork_crosstab = pd.crosstab(formatted_full_df['Artwork'], formatted_full_df['Card type'])
artwork_crosstab
| Card type | Monster Card | Spell Card | Trap Card |
|---|---|---|---|
| Artwork | |||
| (Alternate,) | 81 | 4 | 6 |
| (Alternate, Edited) | 78 | 19 | 20 |
| (Edited,) | 113 | 62 | 43 |
artwork_crosstab_b = pd.crosstab(formatted_full_df['Artwork'], formatted_full_df['Primary type'])
artwork_crosstab_b
| Primary type | Effect Monster | Fusion Monster | Link Monster | Normal Monster | Ritual Monster | Synchro Monster | Xyz Monster |
|---|---|---|---|---|---|---|---|
| Artwork | |||||||
| (Alternate,) | 36 | 12 | 6 | 20 | 0 | 3 | 4 |
| (Alternate, Edited) | 39 | 5 | 7 | 19 | 4 | 0 | 4 |
| (Edited,) | 79 | 7 | 1 | 21 | 2 | 2 | 1 |
More granularity is unnecessary
print('Total number of cards with name or type errata:', formatted_full_df['Errata'].count())
Total number of cards with name or type errata: 1131
formatted_full_df[['Name','Password','TCG status','OCG status','Errata']][formatted_full_df['Errata'].notna()]
| Name | Password | TCG status | OCG status | Errata | |
|---|---|---|---|---|---|
| 0 | "A" Cell Breeding Device | 34541863 | Unlimited | Unlimited | (Name,) |
| 9 | 7 Completed | 86198326 | Unlimited | Unlimited | (Type,) |
| 10 | The A. Forces | 00403847 | Unlimited | Unlimited | (Type,) |
| 20 | Abyss Playhouse - Fantastic Theater | 77297908 | Unlimited | Unlimited | (Name,) |
| 45 | Advanced Heraldry Art | 61314842 | Unlimited | Unlimited | (Name,) |
| ... | ... | ... | ... | ... | ... |
| 12089 | Winged Dragon, Guardian of the Fortress #1 | 87796900 | Unlimited | Unlimited | (Name,) |
| 12090 | Winged Dragon, Guardian of the Fortress #2 | 57405307 | Unlimited | Unlimited | (Name,) |
| 12092 | Winged Sage Falcos | 87523462 | Unlimited | Unlimited | (Name,) |
| 12099 | Wynn the Wind Charmer | 37744402 | Unlimited | Unlimited | (Name,) |
| 12100 | Wynn the Wind Charmer, Verdant | 30674956 | Unlimited | Unlimited | (Name,) |
1131 rows × 5 columns
errata_value_counts = formatted_full_df['Errata'].value_counts()
plt.figure(figsize=(20,8))
venn2(subsets = (errata_value_counts[('Name',)], errata_value_counts[('Type',)],errata_value_counts[('Name','Type')]), set_labels = ('Name Errata', 'Type errata'))
plt.show()
errata_crosstab = pd.crosstab(formatted_full_df['Errata'], formatted_full_df['Card type'])
errata_crosstab
| Card type | Monster Card | Spell Card | Trap Card |
|---|---|---|---|
| Errata | |||
| (Name,) | 311 | 57 | 51 |
| (Name, Type) | 74 | 21 | 2 |
| (Type,) | 397 | 209 | 9 |
errata_crosstab_b = pd.crosstab(formatted_full_df['Errata'], formatted_full_df['Primary type'])
errata_crosstab_b
| Primary type | Effect Monster | Fusion Monster | Link Monster | Normal Monster | Ritual Monster | Synchro Monster | Xyz Monster |
|---|---|---|---|---|---|---|---|
| Errata | |||||||
| (Name,) | 196 | 46 | 4 | 49 | 3 | 9 | 3 |
| (Name, Type) | 39 | 10 | 0 | 18 | 2 | 5 | 0 |
| (Type,) | 271 | 22 | 2 | 61 | 2 | 24 | 15 |
More granularity is unnecessary
errata_crosstab_c = pd.crosstab(formatted_full_df['Artwork'], formatted_full_df['Errata'])
errata_crosstab_c
| Errata | (Name,) | (Name, Type) | (Type,) |
|---|---|---|---|
| Artwork | |||
| (Alternate,) | 8 | 15 | 21 |
| (Alternate, Edited) | 8 | 5 | 13 |
| (Edited,) | 16 | 8 | 38 |
print('Total number of TCG status:', formatted_full_df['TCG status'].nunique())
Total number of TCG status: 7
formatted_full_df.groupby('TCG status', dropna=False).nunique()
| Name | Password | Card type | Property | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | OCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| TCG status | ||||||||||||||||||||
| Forbidden | 99 | 99 | 3 | 7 | 5 | 2 | 6 | 19 | 12 | 27 | 20 | 2 | 4 | 10 | 48 | 54 | 2 | 3 | 4 | 99 |
| Illegal | 38 | 0 | 3 | 3 | 5 | 0 | 6 | 14 | 5 | 11 | 12 | 2 | 2 | 2 | 6 | 7 | 0 | 1 | 1 | 38 |
| Legal | 20 | 0 | 1 | 0 | 1 | 0 | 5 | 11 | 5 | 6 | 7 | 0 | 0 | 0 | 0 | 13 | 2 | 1 | 1 | 20 |
| Limited | 83 | 83 | 3 | 6 | 6 | 3 | 6 | 16 | 9 | 21 | 21 | 3 | 1 | 1 | 42 | 43 | 3 | 3 | 4 | 83 |
| Not yet released | 100 | 88 | 3 | 9 | 6 | 3 | 6 | 19 | 11 | 28 | 25 | 5 | 2 | 4 | 39 | 28 | 0 | 0 | 1 | 100 |
| Semi-Limited | 3 | 3 | 2 | 2 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 3 | 3 | 0 | 1 | 1 | 3 |
| Unlimited | 11327 | 11324 | 3 | 9 | 7 | 6 | 7 | 24 | 14 | 80 | 75 | 13 | 6 | 60 | 343 | 1118 | 3 | 3 | 4 | 11230 |
| NaN | 448 | 332 | 3 | 9 | 8 | 2 | 7 | 24 | 12 | 55 | 38 | 4 | 4 | 8 | 91 | 107 | 1 | 1 | 5 | 448 |
formatted_full_df['TCG status'].value_counts(dropna = False).plot.bar(figsize = (18,6), logy=True, grid = True, rot=45)
plt.show()
# Remove unlimited
tcg_crosstab = pd.crosstab(formatted_full_df['Card type'], formatted_full_df['TCG status']).drop(['Unlimited'], axis=1)
tcg_crosstab
| TCG status | Forbidden | Illegal | Legal | Limited | Not yet released | Semi-Limited |
|---|---|---|---|---|---|---|
| Card type | ||||||
| Monster Card | 64 | 35 | 20 | 43 | 66 | 1 |
| Spell Card | 25 | 2 | 0 | 35 | 21 | 2 |
| Trap Card | 10 | 1 | 0 | 5 | 13 | 0 |
plt.figure(figsize = (12,6))
sns.heatmap(tcg_crosstab, annot=True, fmt="g", cmap='viridis', norm=LogNorm())
plt.show()
# Remove unlimited
tcg_crosstab_b = pd.crosstab(formatted_full_df['Monster type'], formatted_full_df['TCG status']).drop(['Unlimited'], axis=1)
tcg_crosstab_b
| TCG status | Forbidden | Illegal | Legal | Limited | Not yet released | Semi-Limited |
|---|---|---|---|---|---|---|
| Monster type | ||||||
| Aqua | 1 | 0 | 2 | 1 | 2 | 0 |
| Beast | 0 | 3 | 1 | 2 | 3 | 0 |
| Beast-Warrior | 2 | 3 | 0 | 2 | 2 | 0 |
| Cyberse | 2 | 0 | 0 | 1 | 1 | 0 |
| Dinosaur | 0 | 0 | 1 | 2 | 2 | 0 |
| Divine-Beast | 0 | 3 | 0 | 0 | 0 | 0 |
| Dragon | 11 | 3 | 1 | 6 | 6 | 0 |
| Fairy | 3 | 4 | 3 | 1 | 5 | 0 |
| Fiend | 5 | 2 | 4 | 3 | 4 | 0 |
| Fish | 1 | 0 | 0 | 0 | 6 | 0 |
| Insect | 2 | 0 | 0 | 0 | 2 | 0 |
| Machine | 6 | 4 | 3 | 6 | 3 | 0 |
| Plant | 6 | 1 | 0 | 0 | 2 | 0 |
| Psychic | 2 | 1 | 0 | 1 | 5 | 0 |
| Pyro | 0 | 0 | 0 | 0 | 0 | 0 |
| Reptile | 1 | 0 | 1 | 1 | 0 | 0 |
| Rock | 2 | 1 | 1 | 4 | 0 | 0 |
| Sea Serpent | 1 | 0 | 0 | 0 | 1 | 0 |
| Spellcaster | 8 | 5 | 1 | 8 | 2 | 0 |
| Thunder | 1 | 1 | 0 | 0 | 1 | 0 |
| Warrior | 4 | 2 | 2 | 2 | 9 | 1 |
| Winged Beast | 2 | 2 | 0 | 2 | 8 | 0 |
| Wyrm | 4 | 0 | 0 | 1 | 0 | 0 |
| Zombie | 0 | 0 | 0 | 0 | 2 | 0 |
plt.figure(figsize = (20,5))
sns.heatmap(tcg_crosstab_b.T, annot=True, fmt="g", cmap='viridis', square = True, norm=LogNorm())
plt.show()
# Remove unlimited
tcg_crosstab_c = pd.crosstab(exploded_archseries['Archseries'].where(exploded_archseries['OCG status']!='Unlimited'), exploded_archseries['TCG status'], margins = True)
tcg_crosstab_c
| TCG status | Forbidden | Illegal | Legal | Limited | Not yet released | Semi-Limited | Unlimited | All |
|---|---|---|---|---|---|---|---|---|
| Archseries | ||||||||
| -Eyes Dragon | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| A-to-Z | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
| Adventurer Token (series) | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 3 |
| Amazoness | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
| Ancient Gear | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| Zexal | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| Zoodiac | 3 | 0 | 0 | 1 | 0 | 0 | 0 | 4 |
| roid | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
| tellarknight | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| All | 63 | 40 | 16 | 31 | 7 | 4 | 59 | 220 |
122 rows × 8 columns
print('Total number of OCG status:', formatted_full_df['OCG status'].nunique())
Total number of OCG status: 7
formatted_full_df.groupby('OCG status', dropna=False).nunique()
| Name | Password | Card type | Property | Primary type | Secondary type | Attribute | Monster type | Level/Rank | ATK | DEF | Pendulum Scale | Link | Link Arrows | Effect type | Archseries | Artwork | Errata | TCG status | Modification date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| OCG status | ||||||||||||||||||||
| Forbidden | 89 | 89 | 3 | 6 | 5 | 3 | 6 | 19 | 11 | 27 | 22 | 3 | 4 | 8 | 40 | 45 | 2 | 3 | 3 | 89 |
| Illegal | 32 | 1 | 3 | 2 | 6 | 1 | 6 | 12 | 8 | 14 | 15 | 2 | 2 | 2 | 8 | 8 | 0 | 1 | 1 | 32 |
| Legal | 39 | 0 | 1 | 0 | 2 | 0 | 6 | 17 | 7 | 8 | 8 | 0 | 0 | 0 | 0 | 24 | 2 | 1 | 1 | 39 |
| Limited | 71 | 71 | 3 | 6 | 6 | 3 | 6 | 15 | 9 | 18 | 20 | 3 | 3 | 5 | 38 | 39 | 2 | 3 | 3 | 71 |
| Not yet released | 68 | 0 | 3 | 6 | 6 | 1 | 6 | 16 | 11 | 21 | 18 | 3 | 2 | 2 | 35 | 32 | 0 | 0 | 0 | 68 |
| Semi-Limited | 20 | 20 | 3 | 4 | 2 | 0 | 4 | 5 | 4 | 7 | 6 | 1 | 0 | 0 | 15 | 13 | 0 | 1 | 4 | 20 |
| Unlimited | 11757 | 11732 | 3 | 9 | 7 | 6 | 7 | 25 | 14 | 81 | 76 | 13 | 6 | 59 | 350 | 1141 | 3 | 3 | 4 | 11665 |
| NaN | 38 | 14 | 3 | 6 | 6 | 1 | 5 | 14 | 5 | 12 | 13 | 0 | 1 | 1 | 15 | 5 | 0 | 0 | 3 | 38 |
formatted_full_df['OCG status'].value_counts(dropna = False).plot.bar(figsize = (18,6), logy=True, grid = True, rot=45)
plt.show()
# Remove unlimited
ocg_crosstab = pd.crosstab(formatted_full_df['Card type'], formatted_full_df['OCG status']).drop(['Unlimited'], axis=1)
ocg_crosstab
| OCG status | Forbidden | Illegal | Legal | Limited | Not yet released | Semi-Limited |
|---|---|---|---|---|---|---|
| Card type | ||||||
| Monster Card | 57 | 30 | 39 | 39 | 43 | 8 |
| Spell Card | 22 | 1 | 0 | 29 | 19 | 11 |
| Trap Card | 10 | 1 | 0 | 3 | 6 | 1 |
plt.figure(figsize = (12,6))
sns.heatmap(ocg_crosstab, annot=True, fmt="g", cmap='viridis', norm=LogNorm())
plt.show()
# Remove unlimited
ocg_crosstab_b = pd.crosstab(formatted_full_df['Monster type'], formatted_full_df['OCG status']).drop(['Unlimited'], axis=1)
ocg_crosstab_b
| OCG status | Forbidden | Illegal | Legal | Limited | Not yet released | Semi-Limited |
|---|---|---|---|---|---|---|
| Monster type | ||||||
| Aqua | 2 | 0 | 2 | 1 | 1 | 1 |
| Beast | 1 | 2 | 4 | 0 | 1 | 0 |
| Beast-Warrior | 3 | 2 | 0 | 1 | 0 | 1 |
| Creator God | 0 | 0 | 0 | 0 | 0 | 0 |
| Cyberse | 2 | 0 | 2 | 1 | 0 | 0 |
| Dinosaur | 0 | 0 | 1 | 1 | 0 | 0 |
| Divine-Beast | 0 | 3 | 0 | 0 | 0 | 0 |
| Dragon | 10 | 3 | 1 | 4 | 3 | 0 |
| Fairy | 2 | 3 | 4 | 4 | 4 | 0 |
| Fiend | 5 | 1 | 7 | 1 | 7 | 0 |
| Fish | 1 | 0 | 0 | 0 | 1 | 0 |
| Insect | 1 | 0 | 0 | 0 | 7 | 0 |
| Machine | 5 | 3 | 6 | 7 | 4 | 1 |
| Plant | 5 | 0 | 1 | 1 | 1 | 0 |
| Psychic | 1 | 1 | 0 | 3 | 3 | 0 |
| Pyro | 0 | 0 | 1 | 1 | 0 | 0 |
| Reptile | 1 | 0 | 1 | 0 | 0 | 0 |
| Rock | 1 | 1 | 1 | 2 | 1 | 0 |
| Sea Serpent | 1 | 0 | 0 | 0 | 0 | 0 |
| Spellcaster | 7 | 7 | 1 | 8 | 4 | 3 |
| Thunder | 0 | 0 | 1 | 3 | 1 | 0 |
| Warrior | 4 | 3 | 3 | 1 | 2 | 2 |
| Winged Beast | 3 | 1 | 1 | 0 | 1 | 0 |
| Wyrm | 2 | 0 | 0 | 0 | 2 | 0 |
| Zombie | 0 | 0 | 2 | 0 | 0 | 0 |
plt.figure(figsize = (20,5))
sns.heatmap(ocg_crosstab_b.T, annot=True, fmt="g", cmap='viridis', square = True, norm=LogNorm())
plt.show()
# Remove unlimited
ocg_crosstab_c = pd.crosstab(exploded_archseries['Archseries'].where(exploded_archseries['OCG status']!='Unlimited'), exploded_archseries['OCG status'], margins = True)
ocg_crosstab_c
cg_crosstab = pd.crosstab(formatted_full_df['OCG status'],formatted_full_df['TCG status'], dropna=False, margins = False)
cg_crosstab
plt.figure(figsize = (10,8))
sns.heatmap(cg_crosstab, annot=True, fmt="g", cmap='viridis', square=True, norm=LogNorm())
plt.show()
! jupyter nbconvert Cards.ipynb --to=HTML --TemplateExporter.exclude_input_prompt=True --TemplateExporter.exclude_output_prompt=True
formatted_full_df.loc[formatted_full_df['OCG status'] == 'Not yet released'].loc[formatted_full_df['TCG status'] == 'Not yet released']
! git add .
! git commit -m {"Update-" + pd.Timestamp.now().strftime("%d%m%Y")}
! git push